﻿package eu.liquify.ui {
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	public class ListBox extends UIContainer {
		public static var childAliases:Object = { "item": ListItem };
		
		public var select:Function = NULL_FUNCTION;
		
		public var active:ListItem;
		private var collapsed:Boolean = true;
		private var items:Vector.<ListItem> = new Vector.<ListItem>();
		//private var shadow:GlowFilter = new GlowFilter(0x000000, 0);
		private var _activeData:Object;
		
		private var prevWidth:Number;
		private var itemWidth:Number;
		
		public var gridWidth:Number = 50;
		public var gridHeight:Number = 25;
		private var activeSpacing:Number = 5;
		public var pairAutoSwitch:Boolean = false;
		
		private var contentOffset:Point = new Point();
		
		private var labelResizer:LabeledItem;
		
		public function ListBox(listItems:Vector.<ListItem> = null) {
			if (listItems) {
				listItems.forEach(addChild, this);
			}
			
			//debugSize = true;
			
			labelResizer = new LabeledItem( { item: this, reposition: false } );
			addRawChild(labelResizer);
			
			resize();
		}
		
		public function get layoutType():String {
			return labelResizer.layoutType;
		}
		public function set layoutType(v:String):void {
			labelResizer.layoutType = v;
		}
		
		override public function get label():String {
			return labelResizer.label;
		}
		override public function set label(value:String):void {
			labelResizer.label = value;
		}
		
		override public function resize():void {
			super.resize();
			var w:Number = width;
			var h:Number = height;
			labelResizer.itemWidth = gridWidth;
			labelResizer.fixedSize = fixedSize;
			labelResizer.width = w;
			labelResizer.height = h;
			labelResizer.resize();
			itemWidth = width;
			contentOffset.x = labelResizer.width-itemWidth;
			width = labelResizer.width;
			height = labelResizer.height;
			if (itemWidth != prevWidth) {
				prevWidth = itemWidth;
				updateContentSize();
			}
			updateContentPosition();
		}
		
		private function updateContentSize():void {
			if (collapsed) {
				if (active) {
					active.width = itemWidth;
					active.resize();
				}
				redraw(false);
			} else {
				for (var i:int = 0; i < items.length; i++) {
					var m:ListItem = items[i];
					m.width = itemWidth;
					m.resize();
				}
				redraw();
			}
		}
		
		override public function addChild(child:DisplayObject):DisplayObject {
			if (child is ListItem) {
				var m:ListItem = child as ListItem;
				m.fixedSize = true;
				m.centerX = true;
				m.width = itemWidth;
				m.resize();
				m.alpha = 0;
				super.addChild(m);
				m.mouseChildren = m.mouseEnabled = false;
				m.addEventListener(MouseEvent.CLICK, itemClick);
				items.push(m);
				if (items.length == 1) {
					switchTo(m);
				}
			} else {
				super.addChild(child);
			}
			
			return child;
		}
		
		override public function removeChild(child:DisplayObject):DisplayObject {
			if (child is ListItem) {
				var index:int = items.indexOf(m);
				if (index > -1) {
					var m:ListItem = child as ListItem;
					m.removeEventListener(MouseEvent.CLICK, itemClick);
					items.splice(index, 1);
				}
			} else {
				super.removeChild(child);
			}
			
			return child;
		}
		
		public function get activeData():Object { return _activeData; }
		
		public function set activeData(value:Object):void {
			for (var i:int = 0; i < items.length; i++) {
				var m:ListItem = items[i];
				if (m.data == value) {
					switchTo(m);
					break;
				}
			}
		}
		
		private function switchTo(item:ListItem):void {
			active = item;
			_activeData = item.data;
			
			//items[items.indexOf(item)] = items[0];
			//items[0] = item;
			
			if (!collapsed) collapse();
			
			setChildIndex(item, numChildren-1);
			
			item.mouseChildren = item.mouseEnabled = true;
			TweenNano.to(item, 0.1, { "alpha": 1, "x": 0, "y": 0 } );
		}
		private function itemClick(e:MouseEvent):void {
			var item:ListItem = e.currentTarget as ListItem;
			var i:int;
			var m:ListItem;
			var h:Number = activeSpacing+gridHeight;
			if (collapsed && !(pairAutoSwitch && items.length == 2)) {
				collapsed = false;
				for (i = 0; i < items.length; i++) {
					m = items[i];
					//m.filters = [shadow];
					if (m == item) continue;
					
					m.mouseChildren = m.mouseEnabled = true;
					super.addChild(m);
					
					TweenNano.to(m, 0.1, { "alpha": 1, "y": h } );
					h += gridHeight;
				}
				
				removeRawChild(content);
				updateContentPosition();
				stage.addChild(content);
				
				redraw();
				
				stage.addEventListener(MouseEvent.MOUSE_UP, stageCollapse);
			} else {
				if (pairAutoSwitch && items.length == 2) {
					item = item == items[0] ? items[1] : items[0];
				}
				var prev:ListItem = active;
				switchTo(item);
				if (prev != active) {
					Utils.callDynamic(select, this);
					dispatchEvent(new ListEvent(ListEvent.SELECT, item));
				}
			}
		}
		
		private function stageCollapse(e:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, stageCollapse);
			var cur:DisplayObject = e.target as DisplayObject;
			while (cur) {
				var index:int = items.indexOf(cur);
				if (index > -1) {
					return;
				}
				cur = cur.parent;
			}
			switchTo(active);
		}
		
		private function collapse():void {
			if (!collapsed) {
				collapsed = true;
				var i:int;
				var m:ListItem;
				for (i = 0; i < items.length; i++) {
					m = items[i];
					//m.filters = [];
					m.mouseChildren = m.mouseEnabled = false;
					
					TweenNano.to(m, 0.1, { "alpha": 0, "x": 0, "y": 0 } );
				}
				
				stage.removeChild(content);
				updateContentPosition();
				addRawChild(content);
				
				redraw(false);
			}
		}
		
		private function updateContentPosition():void {
			if (collapsed) {
				content.x = contentOffset.x;
				content.y = contentOffset.y;
			} else {
				var p:Point = localToGlobal(contentOffset);
				content.x = p.x;
				content.y = p.y;
			}
		}
		
		private function redraw(draw:Boolean = true):void {
			var g:Graphics = content.graphics;
			g.clear();
			if (draw) {
				g.lineStyle(1, 0xDDDDDD, 1, true);
				g.beginFill(0xF8F8FC);
				//g.drawRoundRect(-3, -4, gridWidth+6, items.length*gridHeight+6, 6, 6);
				g.drawRoundRect(-6, -6, itemWidth+12, items.length*gridHeight+activeSpacing+10, 6, 6);
			}
		}
		
	}
}